﻿#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/ioctl.h>
#include <memory.h>
#include <linux/soundcard.h>
#include <alsa/asoundlib.h>
#include <lame/lame.h>

#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#include <signal.h>
#include "encode.h"
#include "kfifo.h"
#include <pthread.h>

#define DBG printf
//#define DBG(...) do{}while(0)

#define BITRATE 64      //比特率
#define RATE    48000 	//采样频率
#define SOFT_DELAY 2    //缓冲几秒

/*-----------------*/


#define CHANNELS 2  	/*声道数目	*/
#define INBUFF_SIZE (4096*2)  /*PCM读取的BUFF大小，16位, 要乘以声道数，单声channels为1，立体声为2*/
#define MP3BUFF_SIZE (int) (1.25 * INBUFF_SIZE) + 7200//官方推荐大小，类型为int


/*




2.43打布胖am也就1600多的水平，顶级鸟德1400-1500，

 #85UID:62201261 62201261
级别: 学徒威望: 1注册: 20-05-22
2021-04-26 15:33 ★  ⚙ 
 ⯅  ⯆ 

+R by [ningqian] (2021-04-26 13:48)

看了前面楼发的榜和图了吗？最高不超过1700，不知道你说的2.43暗牧能达到2200是有没有相关图能够证明的，还是和3.0版本搞混淆了？

十几年前的狂暴战有现在这么强？没事各个区看看，十几年前会有人几万金冲榜？十几年前naxx能打进一个小时？十几年前有几个工会通？按照现在的发展，我看2200不是难事 
 #86UID:62275275 62275275
级别: 学徒威望: 1注册: 20-06-15
2021-04-26 15:38 ★  ⚙ 
 ⯅  ⯆ 

刚看到别的帖子里的星辰FD布胖的DPS图 第三的AM有2000的秒伤 
 #87UID:9627635 9627635
声望: -750(lv-1)威望: -3(警告1)注册: 11-01-01
2021-04-26 15:44 ★  ⚙ 
 ⯅  ⯆ 

估计很多人都忘了。
暗牧鞭子有个bug，用了就可以比正常伤害高10%左右。
原理就是鞭子3秒跳3次伤害，实际第二下伤害不到2秒就出了，断了鞭子重新拉。
原本6秒2整条鞭子跳6个数字，现在可能能出8次伤害。
确实能增加dps，就是比较麻烦。 
 #88UID:60891473 60891473
级别: 学徒威望: 1注册: 19-09-05
2021-04-26 15:57 ★  ⚙ 
 ⯅ 1 ⯆ 

+R by [古尔丹之撸] (2021-04-26 15:33)

十几年前的狂暴战有现在这么强？没事各个区看看，十几年前会有人几万金冲榜？十几年前naxx能打进一个小时？十几年前有几个工会通？按照现在的发展，我看2200不是难事

“[TBC相关] 有没哪位能记得当年2.43版本下 暗牧在布胖能输出2200 秒伤？” 
看好此贴的内容，注意，是当年2.43版本下 暗牧能否输出2200？ 记住 当年，10多年前，
我们讨论的是当初有没有打到2200,而你说的是未来，也就是即将要开的70级怀旧服；；
要么你贴个10几年前的图，说明AM在2.43能打到2200的证明，
不要说未来，未来是有可能玩出新花样，但我们这个帖子讨论的是当初，不要牛头不对马嘴 
 #89UID:60891473 60891473
级别: 学徒威望: 1注册: 19-09-05
2021-04-26 16:29 ★  ⚙ 
 ⯅  ⯆ 

+R by [六百壮汉] (2021-04-26 15:38)

刚看到别的帖子里的星辰FD布胖的DPS图 第三的AM有2000的秒伤

朋友 星辰公会FD布胖的图，此贴前面楼也有，你应该说的是下面这张图吧，
你看错了，第三是盗贼，淡黄色，2000秒伤，暗牧是白色，您看错颜色了 ，这张FD的图暗牧只有1440；
星辰FD布胖的链接：[http://wow.tgbus.com/class/paladin/200804/20080402143722.shtml]；
 
附件
显示全部附件
 #90UID:63280659 63280659
级别: 学徒威望: 1注册: 21-06-05
2021-06-08 13:15 ★  ⚙ 
 ⯅  ⯆ 

2.43版本AM最高1800多，版本时间短，一个区才只有一两个公会能打SW，装备，团队都有影响 
 #91UID:63280659 63280659
级别: 学徒威望: 1注册: 21-06-05
2021-06-08 13:30 ★  ⚙ 
 ⯅  ⯆ 

+R by [ningqian] (2021-04-26 11:45)

我们团之前2.43卡穆鲁n个cd，开了3.0才过了鸡蛋拿了日咎后武器提升挺大加了70法伤 再加上80级的天赋。才打布胖2000多一些

3..13打2000出头还玩啥AM，虽然过去那么多年了，不太清楚自己最高打到多少，上过一次WMO第一，应该是3800多的布胖。团队要是有爱的话，给灌注激活什么的应该可以上4000，不过很少有团队会为了暗牧打榜。当然现在那些图我也找不到，不过可以给你看下3.0我工会的萨满发的输出到mga之后，别人给我这个牧师的评价
 
附件
显示全部附件
改动
在2021-06-08 13:36修改 
 #92UID:2001500 2001500
声望: 30(lv0)威望: -1(警告1)注册: 09-05-06财富: 3金币56银币
徽章: 猪年大吉:
猪年大吉 一周年:
连续签到一年 猴年大吉:
猴年大吉 爆竹声中旧岁除:
一支红杏出墙来
2021-06-08 14:03 ★  ⚙ 
 ⯅  ⯆ 

2.43那会，我们开荒的时候，打狂暴了，顶了十几秒才过，到现在流程我都记得，先吃屠魔，等cd，急速药水，开打，中途要一瓶大蓝，然后继续急速药水。
打完最高的猎人2000多一点，我是1979。
到中期装备好一点，开荒到穆怒的时候，一般是猎人2200-2300。ss也差不多，团里的工具人am cjq都在1700-1900徘徊，2300那是他吹牛逼 
 #93UID:100558 100558
级别: 学徒威望: 1注册: 05-05-24财富: 60银币52铜币
2021-06-21 14:54 ★  ⚙ 
 ⯅  ⯆ 

+T by [闪电之刃联盟] (2021-04-25 15:13)

1、版本是2.43 (别扯3.0 万年刷马桶，那时候都防骑单T 布胖了)
2、个人不太相信，因为我们当年过布胖，也就法师秒伤达到2300，猎人将将好 2200左右。 我个人不太相信暗牧可以达到。
(当时没有双刀贼，团里3个萨满)

有会里人非要跟我扯，看看是不是我井底之蛙。
我在想是不是2200需要假设：5个萨满 换队给暗牧开英勇，全程敲鼓？

兄弟看图
 
附件
显示全部附件
 #94UID:1053766 1053766
级别: 警告等级1威望: -2注册: 08-07-15财富: 2金币26银币
徽章: 猴年大吉:
猴年大吉
2021-06-21 14:55 ★  ⚙ 
 ⯅  ⯆ 

很多人记忆错乱的，有的甚至没过boss只记住开完英勇就灭后的dps了。 
 #95UID:1457221 1457221
级别: 学徒威望: 1注册: 09-01-04
2021-06-21 15:58 ★  ⚙ 
 ⯅  ⯆ 

当年2.43暗牧布胖能打2300我直播吃翔 
 #96UID:312800 312800
级别: 学徒威望: 2注册: 06-03-02财富: 2金币7银币
2021-06-21 16:12 ★  ⚙ 
 ⯅  ⯆ 

2.43 辅助职业能打到1300就及格了 am怎么可能做得到2000+ 都吹牛批不用成本是吧 
收藏
发表回复
前页
 1 
 2 
 3 
 4 
 5.
到
N G A
燃烧的远征[TBC相关] 有没哪位能记得当年2.43版本下 暗牧在布胖能输出2200 秒伤？
..:: 快速发帖 ::..


未激活的用户可[绑定手机]进行帐号激活 以在论坛发帖
请不要从任何途径购买论坛帐号 论坛备有详细的用户追踪记录 发现盗用帐号或违规激活会立即封禁
如果账号因安全问题而被锁定 请至银色黎明版查看[相关说明]

  
发表回复(Ctrl+Enter)





商务市场合作: BD@donews.com , 内容合作: wangchuang@donews.com / QQ 972310705 , 违法和不良信息举报电话: 010-60845018 邮箱: jubao@infinities.com.cn , 网上有害信息举报专区
京ICP备16021487号-5 京公网安备11010802027588号  
>>>


*/
#define FIFO_SIZE 1024*16*8   //size必须是2的倍数
DECLARE_KFIFO(in_fifobuf, unsigned char, FIFO_SIZE); 
#define inbuf_in(p_data, len) kfifo_in(&in_fifobuf, p_data, len)
#define inbuf_out(p_data, len) kfifo_out(&in_fifobuf, p_data, len)
#define inbuf_init() do{INIT_KFIFO(in_fifobuf); printf("kfifo init %d\n", kfifo_avail(&in_fifobuf));}while(0)
#define inbuf_len() kfifo_len(&in_fifobuf)
#define inbuf_size() kfifo_size(&in_fifobuf)
#define inbuf_clear() kfifo_reset(&in_fifobuf)

static snd_pcm_t *capture_handle;      // PCM设备的句柄
static lame_global_flags* gfp = NULL;  // LAME

static unsigned char vs_encode_flag= 0;
static unsigned int encoder_sta= VS_STA_INIT;
static volatile unsigned char encoder_msg=0;
static unsigned int fifo_threshold = 0 ;

static short input_buff[INBUFF_SIZE*2];
static unsigned char mp3_buff[MP3BUFF_SIZE];

static void _set_fifo_threshold(void)
{
    unsigned int bytes = BITRATE*128; /*= bitrate*1024/8*/
    unsigned int delay_sec= SOFT_DELAY;
    fifo_threshold= bytes*delay_sec;
}

static void _audio_pause(void)
{
    if (snd_pcm_drop(capture_handle) < 0) {
        printf("err %s\n", __func__);
        return;
    }
}

static void _audio_resume(void)
{
    int err;
    if (snd_pcm_state(capture_handle) == SND_PCM_STATE_SUSPENDED) {
        while ((err = snd_pcm_resume(capture_handle)) == -EAGAIN) {
            printf("snd_pcm_state\n");
            sleep(1);
        }
    }
    
    if ((err = snd_pcm_prepare(capture_handle)) < 0) {
        if(err != -EBUSY) {
            printf("%s err: %d %s\n", __func__, err, strerror(errno));
        }
    }
}

static int _capture_snd_init(unsigned int mode, snd_pcm_format_t format, unsigned int rate, unsigned int channels)
{
	snd_pcm_hw_params_t* params;   
    unsigned int set_rate = rate;
    int dir = 0;
    /*1. 打开音频设备*/
    mode = mode ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK;
    //snd_pcm_t *capture_handle =  *p_handle;
    
	if(snd_pcm_open(&capture_handle, "plughw:0,0", mode, 0) < 0) {
		perror("\nopen PCM device failed:");
        return -1;
	}     
    /*2. 分配硬件参数结构*/
    snd_pcm_hw_params_alloca(&params);
    
    /*3. 硬件参数结构初始化*/
	if(snd_pcm_hw_params_any(capture_handle, params) < 0) {
		perror("\nsnd_pcm_hw_params_any:");
		return -1;
	}
     
    /*4. 填写参数结构：数据为交叉模式 SND_PCM_ACCESS_RW_INTERLEAVED*/                                //初始化访问权限
	if(snd_pcm_hw_params_set_access(capture_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
	{
		perror("\nsed_pcm_hw_set_access:");
		return -1;
	}
    /*5. 填写参数结构：PCM数据格式，采样率，声道数*/ 
	if(snd_pcm_hw_params_set_format(capture_handle, params, format) < 0)
	{
		perror("snd_pcm_hw_params_set_format failed:");
		return -1;
	} 
   
	if(snd_pcm_hw_params_set_rate_near(capture_handle, params, &set_rate, &dir) < 0) {
		perror("\nsnd_pcm_hw_params_set_rate_near:");
		return -1;
	}   

	if(snd_pcm_hw_params_set_channels(capture_handle, params, channels) < 0) {
		perror("\nsnd_pcm_hw_params_set_channels:");
		return -1;
	}  
    
    /*6. 参数写入驱动*/
	if(snd_pcm_hw_params(capture_handle, params) < 0) {
		perror("\nsnd_pcm_hw_params:");
		return -1;
	} 
    
//  	/*准备音频接口,并判断是否准备好*/
//	if(snd_pcm_prepare(capture_handle) < 0) {
//		perror("\nsnd_pcm_prepare:");
//		return -1;
//	}

    return 0;              
}


void _print_parm(lame_global_flags *gfp) {   
    printf("default rate is %d, out rate is %d.\n", lame_get_in_samplerate(gfp), lame_get_out_samplerate(gfp));
    printf("default brate is %d.\n", lame_get_brate(gfp));
    printf("default samples is %lu.\n", lame_get_num_samples(gfp));
    printf("default channel is %d.\n", lame_get_num_channels(gfp));
    printf("default vbr_mode is %d.\n", lame_get_VBR(gfp));
    printf("default force_ms is %d.\n", lame_get_force_ms(gfp));
    printf("default mode is %d.\n", lame_get_mode(gfp));
    printf("default compression_ratio is %f.\n", lame_get_compression_ratio(gfp));
    printf("default VBR_mean_bitrate is %d.\n", lame_get_VBR_mean_bitrate_kbps(gfp));
    printf("default quality is %d.\n", lame_get_quality(gfp));  
}


int _lame_start(int rate, int channels) 
{  
    gfp = lame_init(); /*初始化编码器引擎，返回一个lame_global_flags结构体类型指针*/
    if (gfp == NULL) {
        printf("lame_init failed\n");
        return -1;
    }
    /*

    默认是 44.1khz、128kbps，音质是5，需要的时候设置自己的参数覆盖默认
    lame_set_num_channels(gfp,2);
    lame_set_in_samplerate(gfp,44100);  // 采样率 
    lame_set_brate(gfp,128);     // 比特率 
    lame_set_mode(gfp,1);     // mode = 0,1,2,3 = stereo,jstereo,dualchannel(not supported),mono default 
    lame_set_quality(gfp,2);     // 2=high  5 = medium  7=low 
    lame_set_brate(gfp,outBitRate); // 设置比特压缩率，默认为11 
    */
    
    lame_set_in_samplerate(gfp, rate);
    lame_set_brate(gfp, BITRATE);
    lame_set_num_channels(gfp, channels);
    lame_set_quality(gfp, 5);  
    if (lame_init_params(gfp) < 0) {
        printf("lame init params fainld\n");
        lame_close(gfp);
        gfp = NULL;
        return -1;
    }
    _audio_pause();
    //_print_parm(gfp);
    return 0;
}


unsigned char _encoder_init(void)
{
    unsigned char ret = 0;
    unsigned int rate = RATE;
    snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
    if(_capture_snd_init(1, format, rate, CHANNELS)) {
        encoder_sta = VS_STA_HADWARE_ERR;
    }else if(_lame_start(RATE, CHANNELS)){
        encoder_sta = VS_STA_DRVIER_ERR;
    }else {
        encoder_sta = VS_STA_OK;
        ret = 1;
    }
    
    printf("board encoder init %s\n", encoder_visit_staStr());
    return ret;
}


static void _msg_encoder_start(void)
{
    _set_fifo_threshold();
    _audio_resume();
    vs_encode_flag= 1;
}

static void _msg_encoder_stop(void)
{
    _audio_pause();
    vs_encode_flag= 0;
}

static void _msg_encoder_reset(void)
{
    _encoder_init();
    _audio_pause();
    vs_encode_flag= 0;
}


unsigned char _get_encode_sta(void)
{
	return vs_encode_flag;
}

unsigned int _push_data(unsigned char *p_dta, unsigned int len)
{
	return inbuf_in(p_dta, len);
}

static void _handle_msg(void)
{
    if(encoder_sta <= VS_STA_HADWARE_ERR) {
        printf("encoder msg %d pause, sta %d\n", encoder_msg, encoder_sta);
        return ;
    }
    switch(encoder_msg){
    case ENUM_MSG_ENCODER_START:
        printf("encoder msg start\n");
        _msg_encoder_start();
        encoder_msg= 0;
        break;
    case ENUM_MSG_ENCODER_STOP:
        printf("encoder msg stop\n");
        _msg_encoder_stop();
        encoder_msg= 0;
        break;
    case ENUM_MSG_ENCODER_RESET:
        printf("encoder msg reset\n");
        _msg_encoder_reset();
        encoder_msg= 0;
        break;    
    default:  
        break;
        
    }
}

static unsigned int _block_readi(unsigned char* rbuf, unsigned int rbufLen)
{
    int samples;
    int mp3_bytes;
    if(gfp == NULL) {
        return 0;
    }
    samples = snd_pcm_readi(capture_handle, input_buff, INBUFF_SIZE);
	if (samples < 0) {
		perror("Read sound device failed");
        if(samples == -EPIPE) {
        }
		return 0;
	}
    
    if(CHANNELS == 1) {
        mp3_bytes = lame_encode_buffer(gfp, input_buff, input_buff,
                samples, rbuf, rbufLen);
    }else {
        mp3_bytes = lame_encode_buffer_interleaved(gfp, input_buff,
    				samples, rbuf, rbufLen);    
    }          
    
    DBG("samples = %d, mp3_bytes = %d\n", samples, mp3_bytes);
    if (mp3_bytes < 0) {
        printf("lame_encode_buffer_interleaved returned %d\n", mp3_bytes);
    }
    return mp3_bytes;
}


void *_encoder_loop(void *param)
{	
    
    unsigned int len;
	while(1)
	{
        _handle_msg();
		if(_get_encode_sta() == 1) {
	        len = _block_readi(mp3_buff, sizeof(mp3_buff));	
			_push_data(mp3_buff, len);
			encoder_sta = VS_STA_ENCODING;
		}
		else
			encoder_sta = VS_STA_OK;
		usleep(10*1000);
	}
}	

void creat_task_encoder(void)
{
	pthread_t threads;
	int rc;
	long t=0;
    if(_encoder_init()) {
        DBG("encoder init ok\n");
        
        inbuf_init();
    	rc = pthread_create(&threads, NULL, _encoder_loop, (void *)t);
    	if (rc){
    		printf("ERROR; return code from pthread_create() is %d\n", rc);
    		exit(-1);
    	}
    }
}


void encoder_msg_start(void)
{
    encoder_msg = ENUM_MSG_ENCODER_START;
}

void encoder_msg_stop(void)
{
	encoder_msg = ENUM_MSG_ENCODER_STOP;
}

void encoder_msg_reset(void)
{
	encoder_msg = ENUM_MSG_ENCODER_RESET;
}

int encoder_pull_data(unsigned char *p_dta, unsigned int len)
{
    return inbuf_out(p_dta, len);
}

void encoder_clear_cache(void) {
    inbuf_clear();
}

unsigned char encoder_probe(unsigned int len)
{
    if(fifo_threshold != 0){
     /*1. 如果有缓存阈值存在，等待缓存超过阈值*/  
        unsigned int fifosize= inbuf_len();
        if(fifosize > fifo_threshold){
            printf("fifo_threshold clear %d / %d\n", fifosize,  fifo_threshold);
            fifo_threshold= 0;
            return 1;
        }
        else{
            return 0;
        }
    
    } 
    else{
        
    /*2.

    判断缓冲是不为空*/
        return inbuf_len() >= len ? 1 : 0;
    }
   
}

const char* encoder_visit_staStr(void)
{
    const char *str[MAX_ENUM]={
        "初始化",
        "驱动异常",
        "硬件故障",
        "正常",
        "编码中..",
    };
	return str[encoder_sta];
}

unsigned char encoder_fifodep(void)
{
    unsigned char ret = 0;
    if(inbuf_size()) {
        ret = inbuf_len()/inbuf_size();
    }
    return ret;
}



